# import asyncio, time
#
# async def main():
#     print(f'{time.ctime()} Hello!')
#     await asyncio.sleep(1.0)
#     print(f'{time.ctime()} Goodbye!')
#
# asyncio.run(main())

# 1. `loop=asyncio.get_event_loop() 会创建一个event loop的当前线程的instance。如果你已经在一个async def的函数体内的话，你就应该去call astbcui,get running loop()来获得当前instance.
# 2. task = loop.create task(coro())。在案例中的代码调用了main函数。我们的协程函数在放入这么一个task前是不会被执行的。所以也可以理解成，我们通过create task函数来调度协程函数的任务。返回的task对象可以用于监控函数的执行情况（比如是running还是dead)。当然也可以用于获得你的函数执行结果。另外，我们可以通过task.cancel()来终止任务。
#
# 3. loop.run until complete(coro) 调用此函数会阻塞当前主线程。需要注意的是run until complete()会一直运行直到给定的coro任务完成（如果有多个task在任务中那么要等到多个任务都完成）。内部架构上看，asyncio.run()会调用run until complete，所以也会阻塞现成
#
# 4. group=asyncio.gather(task1, task2, task3) 当主线程不阻塞后（或者被loop.stop()叫停，程序会继续向下执行。 这行代码的作用是找到还在pending的任务，取消，然后重新执行一遍。
#
# 5. loop.close()这通常都是最后一步。它只能对已经停止的loop执行。它会清理所有的queues并且关闭executor. 一个停止的协程可以重启，而一个关闭的loop是无法复原的。
#
# Internally,asyncio.run()will close the loop before returning.This is fine becauserun()creates a new event loop every time you call it.
# 另外从第一个代码示例我们可以发现，如果使用asyncio.run()以上那么多复杂的步骤都已经替我们完成了。但理解这些步骤对于实际业务当中的复杂问题是十分重要的。
#
# 另外一个在使用协程的过程中需要注意的事如何创建带有线程阻塞，提供上下文切换功能的函数。 目前python使用await关键字来达成这个目的
# import asyncio
# import time
#
# async def main():
#     print(f"{time.ctime()} Hello!")
#     await asyncio.sleep(1.0)
#     print(f"{time.ctime()} Goodbye!")
#
# loop = asyncio.get_event_loop()
# task = loop.create_task(main())
# loop.run_until_complete(task)
# pending = asyncio.all_tasks(loop=loop)
# for task in pending:
#     task.cancel()
# group = asyncio.gather(*pending, return_exceptions=True)
# loop.run_until_complete(group)
# loop.close()


# 二、async\await 的使用
#
# 正常的函数在执行时是不会中断的，所以你要写一个能够中断的函数，就需要添加async关键。
#
# async 用来声明一个函数为异步函数，异步函数的特点是能在函数执行过程中挂起，去执行其他异步函数，等到挂起条件（假设挂起条件是sleep(5)）消失后，
# 也就是5秒到了再回来执行。
#
# await 用来用来声明程序挂起，比如异步程序执行到某一步时需要等待的时间很长，就将此挂起，
# 去执行其他的异步程序。await 后面只能跟异步程序或有__await__属性的对象，因为异步程序与一般程序不同。
# 假设有两个异步函数async a，async b，a中的某一步有await，当程序碰到关键字await b()后，异步程序挂起后去执行另一个异步b程序，
# 就是从函数内部跳出去执行其他函数，当挂起条件消失后，不管b是否执行完，要马上从b程序中跳出来，
# 回到原程序执行原来的操作。如果await后面跟的b函数不是异步函数，那么操作就只能等b执行完再返回，
# 无法在b执行的过程中返回。如果要在b执行完才返回，也就不需要用await关键字了，直接调用b函数就行。
# 所以这就需要await后面跟的是异步函数了。在一个异步函数中，可以不止一次挂起，也就是可以用多个await
import asyncio



async def get_html(url, name):
    print("%s get %s html start" % (name, url))
    await asyncio.sleep(2)
    print("%s get %s html end" % (name, url))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    # 创建两个协程
    tasks = [
        get_html("http://www.baidu.com", "A"),
        get_html("http://www.souhu.com", "B"),
    ]
    # 启动事件循环并将协程放进去执行
    loop.run_until_complete(asyncio.wait(tasks))

